package com.atguigu.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.atguigu.tingshu.album.AlbumInfoFeignClient;
import com.atguigu.tingshu.common.cache.GuiGuCache;
import com.atguigu.tingshu.common.constant.KafkaConstant;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.service.KafkaService;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.user.*;
import com.atguigu.tingshu.user.mapper.*;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

	@Autowired
	private UserInfoMapper userInfoMapper;

    @Autowired
    private WxMaService wxMaService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private KafkaService kafkaService;

    @Autowired
    private UserPaidAlbumMapper userPaidAlbumMapper;

    @Autowired
    private UserPaidTrackMapper userPaidTrackMapper;

    @Autowired
    private UserVipServiceMapper userVipServiceMapper;

    @Autowired
    private VipServiceConfigMapper vipServiceConfigMapper;

    @Autowired
    private AlbumInfoFeignClient albumFeignClient;
    /**
     * 采用微信JavaSDK进行微信登录
     *
     * @param code
     * @return
     */
    @Override
    public Map<String, String> wxLogin(String code) {
        try {
            //1.根据code调用微信SDK获取用户会话信息-得到微信用户唯一标识(OpenID)（微信端用户标识不变）-大家无法调用（没有在开发者列表）
            WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);
            if (sessionInfo != null) {
                String openid = sessionInfo.getOpenid();
                //2.根据openId查询用户记录   固定写死OpenID odo3j4q2KskkbbW-krfE-cAxUnzU
                LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(UserInfo::getWxOpenId, openid);
                UserInfo userInfo = userInfoMapper.selectOne(queryWrapper);

                //2.1 根据OpenId没有得到用户记录  新增用户记录 且 采用MQ异步初始化账户（余额）信息
                if (userInfo == null) {
                    userInfo = new UserInfo();
                    userInfo.setWxOpenId(openid);
                    userInfo.setNickname("听友" + IdUtil.getSnowflake().nextIdStr());
                    userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
                    userInfoMapper.insert(userInfo);
                    // 发送异步MQ消息，通知账户微服务初始化当前用户账户余额信息
                    kafkaService.sendMessage(KafkaConstant.QUEUE_USER_REGISTER, userInfo.getId().toString());
                }
                //2.2 根据OpenID获取到用户记录，

                //3.为登录微信用户生成令牌，将令牌存入Redis中
                String token = IdUtil.fastSimpleUUID();
                String loginKey = RedisConstant.USER_LOGIN_KEY_PREFIX + token;
                UserInfoVo userInfoVo = BeanUtil.copyProperties(userInfo, UserInfoVo.class);
                redisTemplate.opsForValue().set(loginKey, userInfoVo, RedisConstant.USER_LOGIN_KEY_TIMEOUT, TimeUnit.SECONDS);


                //4.响应令牌
                Map<String, String> mapResult = new HashMap<>();
                mapResult.put("token", token);
                return mapResult;
            }
            return null;
        } catch (WxErrorException e) {
            log.error("微信登录异常：{}", e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 根据用户ID查询用户信息
     * @param userId
     * @return
     */
    @GuiGuCache(prefix = "userInfo")
    @Override
    public UserInfoVo getUserInfo(Long userId) {
        UserInfo userInfo = userInfoMapper.selectById(userId);
        if (userInfo != null){
            return BeanUtil.copyProperties(userInfo, UserInfoVo.class);
        }
        return null;
    }

    /**
     * 修改用户信息
     * @param userId
     * @param userInfoVo
     */
    @Override
    public void updateUser(Long userId, UserInfoVo userInfoVo) {
        //1.先删除缓存
        redisTemplate.delete("userInfo:"+userId);
        UserInfo userInfo = new UserInfo();
        //只允许更新头像、昵称信息
        userInfo.setId(userId);
        userInfo.setNickname(userInfoVo.getNickname());
        userInfo.setAvatarUrl(userInfoVo.getAvatarUrl());
        userInfoMapper.updateById(userInfo);
        // 异步延迟双删
        new Thread(() -> {
            try {
                Thread.sleep(500);  // 延迟500ms
                redisTemplate.delete("userInfo:"+userId);  // 再次删除缓存
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();  // 恢复线程中断状态
            }
        }).start();
    }
    /**
     * 获取专辑声音列表某页中，用户对于声音付费情况
     * @param userId 用户ID
     * @param albumId 专辑ID
     * @param trackIdList 需要判断购买请求声音ID集合（从用户查询专辑声音分页）
     * @return
     */
    @Override
    public Map<Long, Integer> userIsPaidTrackList(Long userId, Long albumId, List<Long> trackIdList) {
        //1.根据用户ID和专辑ID查询用户购买专辑列表，如果有记录将trackIDList购买情况返回1
        LambdaQueryWrapper<UserPaidAlbum> albumLambdaQueryWrapper = new LambdaQueryWrapper<>();
        albumLambdaQueryWrapper.eq(UserPaidAlbum::getUserId, userId).eq(UserPaidAlbum::getAlbumId, albumId);
        List<UserPaidAlbum> albumList = userPaidAlbumMapper.selectList(albumLambdaQueryWrapper);
        if (albumList != null && albumList.size() > 0){
            return  trackIdList.stream().collect(Collectors.toMap(trackId -> trackId, trackId -> 1));
        }
        //2.根据用户ID和专辑ID和声音列表查询用户购买专辑列表，判断哪些声音被购买，哪些没有被购买
        LambdaQueryWrapper<UserPaidTrack> trackLambdaQueryWrapper = new LambdaQueryWrapper<>();
        trackLambdaQueryWrapper.eq(UserPaidTrack::getUserId, userId).in(UserPaidTrack::getTrackId, trackIdList);
        List<UserPaidTrack> userPaidTrackList = userPaidTrackMapper.selectList(trackLambdaQueryWrapper);
        if (userPaidTrackList != null && userPaidTrackList.size() > 0){
            Map<Long, Integer> UserPaidTrackMap = userPaidTrackList.stream().collect(Collectors.toMap(userPaidTrack -> userPaidTrack.getTrackId(), userPaidTrack -> 1));
            for (Long trackId : trackIdList) {
                Integer status = UserPaidTrackMap.get(trackId);
                if(status == null){
                    UserPaidTrackMap.put(trackId, 0);
                }
            }
            return UserPaidTrackMap;
        }
        return  trackIdList.stream().collect(Collectors.toMap(trackId -> trackId, trackId -> 0));
    }

    /**
     * 判断用户是否购买过指定专辑
     *
     * @param userId
     * @param albumId
     * @return
     */
    @Override
    public Boolean isPaidAlbum(Long userId, Long albumId) {
        LambdaQueryWrapper<UserPaidAlbum> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserPaidAlbum::getUserId, userId);
        queryWrapper.eq(UserPaidAlbum::getAlbumId, albumId);
        Long count = userPaidAlbumMapper.selectCount(queryWrapper);
        return count > 0;
    }

    /**
     * 根据专辑id+用户ID获取用户已购买声音id列表
     *
     * @param albumId
     * @return
     */
    @Override
    public List<Long> getUserPaidTrackList(Long userId, Long albumId) {
        LambdaQueryWrapper<UserPaidTrack> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserPaidTrack::getUserId, userId);
        queryWrapper.eq(UserPaidTrack::getAlbumId, albumId);
        List<UserPaidTrack> userPaidTrackList = userPaidTrackMapper.selectList(queryWrapper);
        if (CollectionUtil.isNotEmpty(userPaidTrackList)) {
            //获取已购声音ID列表
            List<Long> userPaidTrackIdList = userPaidTrackList.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
            return userPaidTrackIdList;
        }
        return null;
    }




    /**
     * 处理用户购买记录
     * 1.处理声音购买记录-根据订单编号避免重复增加购买记录
     * 2.处理专辑购买记录-根据订单编号避免重复增加购买记录
     * 3.处理会员购买记录
     * -根据订单编号避免重复增加购买记录
     * -修改用户表VIP状态及失效时间
     *
     * @param userPaidRecordVo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveUserPayRecord(UserPaidRecordVo userPaidRecordVo) {
        //1.处理声音购买记录
        if (SystemConstant.ORDER_ITEM_TYPE_TRACK.equals(userPaidRecordVo.getItemType())) {
            //1.1 根据订单编号避免重复增加购买记录
            LambdaQueryWrapper<UserPaidTrack> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserPaidTrack::getOrderNo, userPaidRecordVo.getOrderNo());
            Long count = userPaidTrackMapper.selectCount(queryWrapper);
            if (count > 0) {
                return;
            }
            //1.2 构建声音购买记录新增
            //1.3 远程调用专辑服务获取声音信息
            TrackInfo trackInfo = albumFeignClient.getTrackInfo(userPaidRecordVo.getItemIdList().get(0)).getData();
            userPaidRecordVo.getItemIdList().forEach(trackId -> {
                UserPaidTrack userPaidTrack = new UserPaidTrack();
                userPaidTrack.setOrderNo(userPaidRecordVo.getOrderNo());
                userPaidTrack.setUserId(userPaidRecordVo.getUserId());
                userPaidTrack.setAlbumId(trackInfo.getAlbumId());
                userPaidTrack.setTrackId(trackId);
                userPaidTrackMapper.insert(userPaidTrack);
            });
        } else if (SystemConstant.ORDER_ITEM_TYPE_ALBUM.equals(userPaidRecordVo.getItemType())) {
            //2.处理专辑购买记录
            //2.1 根据订单编号避免重复增加购买记录
            LambdaQueryWrapper<UserPaidAlbum> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserPaidAlbum::getOrderNo, userPaidRecordVo.getOrderNo());
            Long count = userPaidAlbumMapper.selectCount(queryWrapper);
            if (count > 0) {
                return;
            }
            //2.2 新增专辑购买记录
            userPaidRecordVo.getItemIdList().forEach(albumId -> {
                UserPaidAlbum userPaidAlbum = new UserPaidAlbum();
                userPaidAlbum.setOrderNo(userPaidRecordVo.getOrderNo());
                userPaidAlbum.setUserId(userPaidRecordVo.getUserId());
                userPaidAlbum.setAlbumId(albumId);
                userPaidAlbumMapper.insert(userPaidAlbum);
            });
        } else if (SystemConstant.ORDER_ITEM_TYPE_VIP.equals(userPaidRecordVo.getItemType())) {
            //3.处理会员购买记录
            //3.1-根据订单编号避免重复增加购买记录
            LambdaQueryWrapper<UserVipService> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserVipService::getOrderNo, userPaidRecordVo.getOrderNo());
            Long count = userVipServiceMapper.selectCount(queryWrapper);
            if (count > 0) {
                return;
            }
            //3.2-修改用户表VIP状态及失效时间
            Date startTime = new Date();
            //2.1.1 获取用户
            UserInfo userInfo = userInfoMapper.selectById(userPaidRecordVo.getUserId());
            //2.1.2 根据套餐ID查询VIP套餐信息
            VipServiceConfig vipServiceConfig = vipServiceConfigMapper.selectById(userPaidRecordVo.getItemIdList().get(0));
            Date expireTime = new Date();


            //刚购买VIP VIP开始时间-当前，过期时间：当前时间+购买月数
            //已是VIP且在有效期，过期时间：现有失效时间+购买月数
            if (userInfo.getIsVip() == 1 && userInfo.getVipExpireTime().after(new Date())) {
                expireTime = DateUtil.offsetMonth(userInfo.getVipExpireTime(), vipServiceConfig.getServiceMonth());
            } else {
                //首次购买会员-过期时间
                expireTime = DateUtil.offsetMonth(startTime, vipServiceConfig.getServiceMonth());
            }
            userInfo.setIsVip(1);
            userInfo.setVipExpireTime(expireTime);
            userInfoMapper.updateById(userInfo);

            //3.3-新增用户VIP购买记录
            for (Long vipConfigId : userPaidRecordVo.getItemIdList()) {
                UserVipService userVipService = new UserVipService();
                userVipService.setOrderNo(userPaidRecordVo.getOrderNo());
                userVipService.setUserId(userPaidRecordVo.getUserId());
                userVipService.setStartTime(startTime);
                userVipService.setExpireTime(expireTime);
                userVipService.setIsAutoRenew(0);
                userVipService.setNextRenewTime(null);
                userVipServiceMapper.insert(userVipService);
            }

        }
    }

    /**
     * 更新Vip到期失效状态
     *
     * @return
     */
    @Override
    public void updateVipExpireStatus() {
        //1.已经过期会员
        LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserInfo::getIsVip, "1");
        queryWrapper.lt(UserInfo::getVipExpireTime, DateUtil.beginOfDay(new Date()));
        List<UserInfo> list = this.list(queryWrapper);
        //2.批量更新
        if (CollectionUtil.isNotEmpty(list)) {
            List<UserInfo> collect = list.stream().map(userInfo -> {
                UserInfo userInfo1 = new UserInfo();
                userInfo1.setIsVip(0);
                userInfo1.setId(userInfo.getId());
                return userInfo1;
            }).collect(Collectors.toList());
            this.updateBatchById(collect);
        }
    }
}
